<html>
<head>
  <title>Evernote Export</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/602988 (zh-CN, DDL); Windows/10.0.0 (Win64); EDAMVersion=V2;"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="504"/>

<div>
<span><div><font style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">事件委托</span></font></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>原理：利用冒泡的原理,把事件添加到父元素上,委托它们父级代为执行事件；</div><div>优点：提高性能,减少内存消耗,对于新添加的元素也会有之前的事件；</div><div>缺点：1.事件委托基于冒泡,不冒泡的事件不支持；2.层级过多,冒泡过程中可能被中间层阻止；3.如果把所有事件都用事件委托,可能会出现事件误判,即不该触发事件的被绑定了；</div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">通过e.</span>target.dataset来获取子节点上绑定的自定义属性的值</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">闭包</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>在MDN中闭包的解释：</div><div>    闭包（closure）是一个函数以及其捆绑的周边环境状态（lexical environment，词法环境）的引用的组合。可以让开发者从内部函数访问外部函数的作用域。在 JavaScript 中，闭包会随着函数的创建而被同时创建。他有三个特性</div><div>* 函数嵌套函数</div><div>* 函数内部可以引用函数外部的参数和变量</div><div>* 参数和变量不会被垃圾回收机制回收</div><div><br/></div><div>优点：可以重复使用变量，并且不会造成变量污染</div><div>缺点：比普通函数更占用内存，会导致网页性能变差，大量创建闭包容易造成内存泄露。</div><div>      (因为闭包就是能够访问外部函数变量的一个函数，而函数是必须保存在内存中的对象，所以位于函数执行上下文中的所有变量也需要保存在内存中，这样就不会被回收，如果一旦循环引用或创建闭包，就会占据大量内存，可能会引起内存泄漏)</div><div><br/></div><div>使用场景：节流、防抖、循环定时器打印i...</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">节流与防抖</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>防抖：持续触发时最后一次触发的一段时间后执行函数；</div><div>节流：在一段时间内，只执行一次函数；</div><div>https://zhuanlan.zhihu.com/p/72923073</div><div><br/></div><div>function debounce(func, delay) {</div><div>  let timeout</div><div>  return function() {</div><div>    clearTimeout(timeout) // 如果持续触发，那么就清除定时器，定时器的回调就不会执行。</div><div>    timeout = setTimeout(() =&gt; {</div><div>      func.apply(this, arguments)</div><div>    }, delay)</div><div>  }}</div><div><br/></div><div>function throttle(func, delay) {</div><div>    let run = true</div><div>    return function () {</div><div>      if (!run) {</div><div>        return  // 如果开关关闭了，那就直接不执行下边的代码</div><div>      }</div><div>      run = false // 持续触发的话，run一直是false，就会停在上边的判断那里</div><div>      setTimeout(() =&gt; {</div><div>        func.apply(this, arguments)</div><div>        run = true // 定时器到时间之后，会把开关打开，我们的函数就会被执行</div><div>      }, delay)</div><div>    }</div><div>  }</div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">内存泄漏</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>首先，需要了解浏览器自身的内存回收机制。</div><div>每个浏览器会有自己的一套回收机制，当分配出去的内存不使用的时候便会回收；内存泄露的根本原因就是你的代码中分配了一些‘顽固的’内存，浏览器无法进行回收，如果这些’顽固的’内存还在一直不停地分配就会导致后面所用内存不足，造成泄露。</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">浅拷贝深拷贝</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7072528644739956773#heading-9</div><div>浅拷贝和深拷贝都是创建一份数据的拷贝。</div><div>JS 分为原始类型和引用类型，对于原始类型的拷贝，并没有深浅拷贝的区别，我们讨论的深浅拷贝都只针对引用类型。</div><div>* 浅拷贝和深拷贝都复制了值和地址，都是为了解决引用类型赋值后互相影响的问题。</div><div>* 但是浅拷贝只进行一层复制，深层次的引用类型还是共享内存地址，原对象和拷贝对象还是会互相影响。</div><div>* 深拷贝就是所有层级拷贝，深拷贝后的原对象不会和拷贝对象互相影响。</div><div><br/></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">浅拷贝的方法：Object.assign，slice，concat，扩展运算符，lodash的clone；</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">深拷贝的方法：</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    1、反序列化（部分类型数据丢失或错乱，例如：对象，函数，undefined，正则，NAN等等）</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    2</span>、deepClone方法</div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    3、手写：</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">        ①、</span>先for in循环实现一个浅拷贝</div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">        ②、判断每一项是否是基本数据类型，是则直接拷贝，否则则是复杂数据类型，递归遍历</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">        ③、特殊类型特殊处理，例如：数组，正则，日期，null，Symbol等等</span></div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">bind/apply/call</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>他们三个都是用来改变函数内部this的指向的；</div><div>区别：</div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">1、apply和call都是自调用，bind则需要自己主动去调用；</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">2、bind和call传参都是从第二个参数位置依次写入，而apply则是在第二个参数位置以数组的形式传参</span></div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">重绘</span><span style="font-size: 16pt; font-weight: bold;">和</span><span style="font-size: 16pt; font-weight: bold;">回流</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>重绘： DOM树没有元素增加或删除，只是样式的改变 (比如修改了颜色或背景色)，针对浏览器对某一元素进行单独的渲染，这个过程叫做重绘 回流： 当我们对 DOM 的修改引发了 DOM 几何尺寸的变化（比如修改元素的宽、高或隐藏元素等）时，浏览器需要重新计算元素的几何属性（其他元素的几何属性和位置也会因此受到影响），然后再将计算的结果绘制出来。 这个过程就是回流（也叫重排）。 区别： (重点) 回流比重绘更加的消耗性能，发生回流必定会重绘，重绘却不一定会导致回流。</div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">跨域</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>当请求url的协议、域名、端口号有任意一个不相同时就发生了跨域</div><div><font face="Monaco">解决方法：</font></div><div>1、JSONP（利用 script 标签，规避跨域，发出请求，在服务器代码中调用客户端方法，传递数据，&lt;script src=&quot;url&quot;&gt;。；简单适用，只支持get请求不支持post请求）</div><div>2、CORS</div><div>3、反向代理</div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">递归</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div><font face="Monaco">概念：函数自己调用自己（必须要有终止条件）</font></div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">虚拟DOM，DIFF算法</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://blog.csdn.net/weixin_44972008/article/details/115620198（手写diff）</div><div><br/></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">个人总结：diff算法就是通过新旧虚拟dom的比较，计算出两者之间的最小变化，根据这一变化来更新真实dom的过程；</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">1、</span>虚拟dom:<span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">用来表现真实dom的js对象</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">        { sel: '标签名', data: { props: { id: myid } }, children: [], text: '文字', key: '唯一标识', elm: '对应的真实dom' }</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">2、h函数：主要作用是用来生成虚拟节点，嵌套使用可以生成虚拟dom树，主要内容是函数重载，最后通过vnode函数</span>将传入的参数组合成对象返回</div><div>    export default function(sel, data, children, text, elm) { </div><div>        const key = data.key; </div><div>        return { sel, data, children, text, elm, key }; </div><div>    }</div><div>3、patch函数: 将虚拟dom树上树，过程如下图一，若不是同一个节点则通过creatElement函数结合insertBefore插入新节点，若是同一个节点则通过patchVnode函数精细化比较，如下图二</div><div>4、creatElementh函数: 根据sel通过creatElement方法创建孤儿节点，若存在text则使用innerText来创建文本，若存在children则递归循环调用通过appendChild方法上dom树，最后补充虚拟节点的elm属性</div><div>4、判断新旧vnode是否是同一个节点：sel相同，key相同</div><div>5、若新老vnode都有children，则通过updateChildren函数进行四种命中查找策略，如下图三，命中一种就不会在进行命中判断了，若都没有命中，则通过key循环查找，若newVndoe还有剩余节点没有处理，则通过insertBefore方法添加，若oldVnode还有剩余节点没有处理，则通过removeChild方法删除</div><div><br/></div></div><div><br/></div><div><img src="前端笔记_files/20210412203424571.png" type="image/png" data-filename="20210412203424571.png" width="290"/> <img src="前端笔记_files/20210414151721159.png" type="image/png" data-filename="20210414151721159.png" width="329"/></div><div><br/></div><div><img src="前端笔记_files/20210414191540816.png" type="image/png" data-filename="20210414191540816.png" width="466"/></div><div><br/></div><div><br/></div><div><span style="font-size: 21.3333px; font-weight: bold;">为什么vue在部分情况下不能用index作为key</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7147174440025980935#heading-2</div><div><br/></div><div>1、使用index作为key，会导致diff中的优化失效（降低了复用性，违背了虚拟DOM的初衷）。原本可以复用的东西，不能被复用，徒然增加了性能开销，浪费性能</div><div>2、在删除或插入数据时，因为vue不会深入的区对比子组件的文本内容，所以会错误移除VDOM中的节点（index的值是不固定的）。</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">substr, substring, split, splice, slice, join方法总结</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://www.jianshu.com/p/3f91f46cdea0</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">filter、map、forEach、find、findIndex、some、every方法总结</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://blog.csdn.net/wang_xiao_ye/article/details/89385023?depth_1-utm_source=distribute.pc_relevant_right.none-task-blog-BlogCommendFromBaidu-9&amp;utm_source=distribute.pc_relevant_right.none-task-blog-BlogCommendFromBaidu-9</div><div><br/></div><div><font face="Monaco">易错点</font></div><div>https://juejin.cn/post/6844903814030426125</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">reduce</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://blog.csdn.net/qq_38970408/article/details/121018660</div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">原型链</span></span></div><div><span style="font-size: 21.3333px;"><br/></span></div><div><img src="前端笔记_files/Image.png" type="image/png" data-filename="Image.png" width="484"/></div><div><br/></div><div><br/></div><div><img src="前端笔记_files/Image [1].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">for循环中var和let的区别</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>for(var i = 0; i&lt;5;i++){</div><div>  setTimeout(()=&gt;console.log(i),0) // 5 5 5 5 5</div><div>}</div><div>for(let i = 0; i&lt;5;i++){</div><div>  setTimeout(()=&gt;console.log(i),0) // 0 1 2 3 4</div><div>}</div><div>setTimeout会被放在异步任务中，当主线程执行完了才会执行任务队列中的程序</div><div>var是全局变量，所以循环结束后值会被覆盖掉</div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">let会创造出一个块级作用域，并将变量的值保存在这个子作用域中</span></div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">阻止事件冒泡</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>// 阻止事件冒泡</div><div>  function noclickFrame(e) {</div><div>    //如果提供了事件对象，则这是一个非IE浏览器</div><div>    if ( e &amp;&amp; e.stopPropagation ){</div><div>        //因此它支持W3C的stopPropagation()方法</div><div>      e.stopPropagation();</div><div>    }</div><div>    else { </div><div>        //否则，我们需要使用IE的方式来取消事件冒泡</div><div>        window.event.cancelBubble = true;</div><div>    }</div><div>  }</div></div><div><br/></div><div><span style="font-size: 21.3333px; font-weight: bold;">阻止浏览器默认事件</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>if (e.preventDefault) {</div><div> e.preventDefault(); </div><div>} else {</div><div> // 兼容 IE9- e.returnValue = false;</div><div>}</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">BFC</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://www.bilibili.com/video/BV1aZ4y1M7gW/?spm_id_from=333.337.search-card.all.click&amp;vd_source=bae70ae66df3655386be5075fe93833c</div><div><br/></div><div>个人总结：可以理解为css中的块级作用域，内部元素样式不会受外部元素样式影响</div><div><font face="Monaco">如何触发BFC：</font></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    1、根元素html</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    2、浮动元素（float不是none）</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    3、脱离标准流的定位元素</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    4、display为inline-block、table-cell、table...</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    5、overflow值不为visible的块元素</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    6、contain值为layout、content或paint的元素</span></div><div><span style="font-size: 9pt; color: rgb(51, 51, 51); font-family: Monaco;">    7、多列容器（元素column-count或column-width不为auto，包括column-count为1）</span></div><div><font face="Monaco">作用：</font></div><div><font face="Monaco">    1、可以避免外边距重叠</font></div><div><font face="Monaco">    2、清除浮动</font></div><div><font face="Monaco">    3、阻止元素被浮动元素覆盖</font></div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">ES6</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://github.com/able8/hello-es6</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">Vue MVVM和MVC的区别</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/6879300070962003982</div><div><br/></div><div>MVVM -Model View ViewModel，它包括 DOM Listenters 和 Data bindings，前者实现了页面与数据的绑定，当数据发生变化的时候会自动渲染页面。后者实现了数据与页面的绑定，当页面操作数据的时候 DOM 和 Model 也会发生相应的变化。</div><div><br/></div><div>MVC - Model View Controller( controller: 控制器 )，M 和 V 和 MVVM 中的 M 和 V 意思一样，C 指页面业务逻辑。使用 MVC 的目的就是将 M 和 V 的代码分离，但 MVC 是单向通信，也就是将 Model 渲染到 View 上，必须通过 Controller 来承上启下。</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">Vue双向绑定原理</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7117424554107994120#heading-1</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">Vue响应式原理</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://www.bilibili.com/video/BV1u4411W7ei?p=3&amp;spm_id_from=pageDriver</div><div><br/></div><div>https://segmentfault.com/a/1190000006599500</div><div><br/></div><div>Vue2采用数据劫持结合发布者-订阅者模式的方式，通过Object.defineProperty（）来劫持各个属性的setter，getter，在数据变动时发布消息给订阅者，触发相应监听回调。（其中Object.defineProperty方法有三个参数（修改的对象，修改对象的属性名，属性描述），属性描述对象有4个属性2个方法：</div><div>·  value: 设置属性的值</div><div>·  writable: 值是否可以重写。true | false</div><div>·  enumerable: 目标属性是否可以被枚举。true | false</div><div>·  configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false</div><div>·  set: 目标属性设置值的方法</div><div>·  get：目标属性获取值的方法</div><div>）</div><div>每次通过点语法获取属性都会执行这里的getter函数，在这个函数中我们会把调用此属性的依赖收集到一个集合中 ；而在我们给属性赋值(修改属性)时，会触发这里定义的setter函数，在此函数中会去通知集合中的依赖更新，做到数据变化驱动视图更新。</div><div><br/></div><div>Vue3的Proxy劫持了整个对象，删除了$set方法，相比Object.defineProperty在处理数组和新增属性的响应式处理上更加方便。</div><div><br/></div><div>具体实现是将MVVM作为数据绑定的入口，整合Observer，Compile和Watcher三者.</div><div>通过Observer来对model数据对象的所有属性进行监听，如有变动可拿到最新值并通知订阅者;</div><div>通过Compile来解析编译模板指令（vue中是用来解析 {{}}）对每个元素节点的指令进行扫描和解析，根据指令模板替换数据，以及绑定相应的更新函数；</div><div>通过watcher搭起observer和Compile之间的通信桥梁，订阅并收到每个属性变动的通知，执行指令绑定的相应回调函数，从而更新视图</div></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt;"><br/></span></span></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">Promise</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7144308012952322084#heading-5</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">Async/Await</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div><font face="Monaco">作用： 用同步的方式来书写异步代码</font></div><div>* 语义化强</div><div>* 里面的await只能在async函数中使用</div><div>* await后面的语句可以是promise对象、数字、字符串等</div><div>* async函数返回的是一个Promsie对象</div><div>* await语句后的Promise对象变成reject状态时，那么整个async函数会中断，后面的程序不会继续执行</div><div>1、https://juejin.cn/post/7033647059378896903#heading-6</div><div>2、https://juejin.cn/post/7052906270247878664</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">JS执行机制</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7019214502562365477</div><div><br/></div><div>https://juejin.cn/post/6844903638238756878（更准确一点）</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">nextTick</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>JS是单线程的，拥有事件循环机制，Vue中 数据变化 =&gt; DOM变化 是异步过程，vue采用 Promise、setTimeout、setImmediate 等方式，生成一个延迟任务，在下一个Dom更新循环之后才执行</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">GET/POST</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>1、get参数通过url传递，post放在request body中。</div><div>2、get请求在url中传递的参数是有长度限制的，而post没有。</div><div>3、get请求只能进行url编码，而post支持多种编码方式</div><div>4、get比post更不安全，因为参数直接暴露在url中，所以不能用来传递敏感信息。</div><div>5、get请求参数会被完整保留在浏览历史记录里，而post中的参数不会被保留。</div><div>6、GET产生一个TCP数据包；POST产生两个TCP数据包</div><div>    对于GET方式的请求，浏览器会把http header和data一并发送出去，服务器响应200（返回数据）；</div><div>而对于POST，浏览器先发送header，服务器响应100 continue，浏览器再发送data，服务器响应200 ok（返回数据）。</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">HTTP/HTTPS</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>1、HTTPS是HTTP协议的安全版本，HTTP协议的数据传输是明文的，是不安全的，HTTPS使用了SSL/TLS协议进行了加密处理。</div><div>2、http和https使用连接方式不同，默认端口也不一样，http是80，https是443。</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">ES5、ES6继承</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7069403417906528264#heading-5</div><div><br/></div><div>es5:</div><div>* 说到js继承，最开始想到的应该是是原型链继承，通过把子类实例的原型指向父类实例来继承父类的属性和方法，但原型链继承的缺陷在于对子类实例继承的引用类型的修改会影响到所有的实例对象以及无法向父类的构造方法传参。</div><div>* 构造函数继承, 通过在子类构造函数中调用父类构造函数并传入子类this来获取父类的属性和方法，但构造函数继承也存在缺陷，构造函数继承不能继承到父类原型链上的属性和方法。</div><div>* 后面有了组合式继承，但也有了新的问题，每次都会执行两次父类的构造方法，最终有了寄生式组合式继承</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">New关键字实现了什么</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7071973089076051981/</div><div><br/></div><div>1. 创建一个空对象 </div><div>2. 将空对象的__proto__指向构造函数的原型</div><div>3. 将新对象作为构造函数的执行上下文（即this）</div><div>4. 返回这个新对象</div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">无感刷新Token</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7018439775476514823</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;"> npm run serve执行了什么</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7078924628525056007</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;"> Vuex</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/6928468842377117709#heading-13</div></div><div><br/></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;"> VueRouter两种模式</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7127143415879303204#heading-3</div><div>https://github.com/forthealllight/blog/issues/37</div><div><br/></div><div>* hash模式：通过onHashchange事件来监听路由变化，hash值发生改变，触发事件，查找对应的代码块或组件，替换到router-view中，从而实现视图更新。会向浏览器历史栈中添加记录，但不会刷新页面。缺点是有#比较丑</div><div><br/></div><div>* history模式：通过pushState及replaceState两个方法来操作实现 URL 的变化，并向历史栈添加或者更新记录； 通过popstate 事件来监听 url 的变化；history.pushState() 或 history.replaceState() 不会触发 popstate 事件，这时我们需要手动触发页面跳转(渲染)。缺点是：需要后端配合，在跳转后刷新页面可能会404，需要后端在Nginx中配置重定向</div></div><div><br/></div><div><span style="font-size: 16pt; font-weight: bold;">权限管理</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/6844903648057622536#heading-6</div><div><br/></div><div><font face="Monaco">前端权限一般分为：接口权限，路由权限，按钮权限，菜单权限</font></div><div><font face="Monaco">接口权限一般由token来实现：</font></div><div><font face="Monaco">后三者首先通过菜单管理去配置目录/菜单/按钮中的，名称，组件路径，路由url，icon，排序，权限标识等等，然后通过角色管理来配置每个角色下的访问或者说显示权限。并由后端处理为扁平化一维数组在登录完成后返回给前端，前端拿到后保存到vuex和本地缓存中，在转化为树状结构后通过addroutes动态挂载路由，通过v-permission自定义指令或者自定义工具函数结合v-if的方式来控制访问和显示权限，来实现权限管理</font></div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">虚拟列表</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7085941958228574215</div></div><div><br/></div><div><span style="font-size: 21.3333px;"><span style="font-size: 21.3333px; font-weight: bold;">面试题锦集</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/6984210440276410399#heading-49</div><div>https://juejin.cn/post/6844904084374290446</div></div><div><br/></div><div><span style="font-size: 21.3333px; font-weight: bold;">前端优化方案</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div><span style="font-family: Monaco;">路由懒加载，图片懒加载，分页加载，精灵图，图片压缩，keep-alive组件缓存，gzip压缩，组件库按需引入， 生产环境删除console，防抖节流，</span></div><div><span style="font-family: Monaco;">无感刷新token，虚拟列表</span></div><div><span style="font-family: Monaco;">--report分析包大小 cdn引入，工具函数上传npm库，ssr服务端渲染提高首屏加载速度实现seo优化</span></div></div><div><br/></div><div><span style="font-size: 21.3333px; font-weight: bold;">webpack基础知识</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7157998164627161095</div><div>https://juejin.cn/post/6854573215650414600?searchId=20230816172335BDCB86D6A398DD7661FB</div></div><div><br/></div><div><span style="font-size: 21.3333px; font-weight: bold;">vite常见面试题</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7162096443832926244</div></div><div><br/></div><div><span style="font-size: 21.3333px; font-weight: bold;">TS基础</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://blog.csdn.net/weixin_67745264/article/details/125685828?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-9-125685828-blog-127948273.235^v38^pc_relevant_anti_vip_base&amp;spm=1001.2101.3001.4242.6&amp;utm_relevant_index=10</div></div><div><br/></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">Vue2和Vue3的区别</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>1、响应式不同</div><div>    Vue2通过Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现响应式的,这种方式有一些缺点，例如：无法监听数组下标的变化；无法处理新增属性和删除属性；一次只能对一个属性实现数据挟持，需要递归遍历所有属性进行挟持。</div><div>    Vue3利用 Proxy 实现数据挟持，代理的是整个对象，所以在vue3中也就没有了$set这个方法。性能上proxy会更加优秀。</div><div>2、diff算法</div><div>    vue2 diff 算法就是进行虚拟节点对比，并返回一个 patch 对象，用来存储两个节点不同的地方，然后通过patch对象记录的信息去局部更新 Dom。 它会比较每一个 vnode,而对于一些不参与更新的元素，进行比较是有点消耗性能的。</div><div>vue3 diff 算法在初始化的时候会给每个虚拟节点添加一个 patchFlags，patchFlags 就是优化的标识。 只会比较 patchFlags 发生变化的 vnode,进行更新视图，对于没有变化的元素做静态标记，在渲染的时候直接复用，大大减少了性能消耗。</div><div>3、写法不同</div><div>    Vue2采用Options Api，Vue3则采用Composition API，代码更加简洁，复用性更强，易于后期维护</div><div>4、生命周期不同</div><div>    在大多数生命周期前增加了on，新增了setup，该生命周期位于created之前。3.2新增setup语法糖，写法更加方便</div><div>5、Vue3可以多个根节点</div></div><div><br/></div><div><span style="font-size: 21.3333px; font-weight: bold;">ref和reactive的区别</span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>1、ref 和 reactive操作的数据类型不同</div><div>    * ref：将数据变为响应式数据，可用于基本数据类型 和 引用数据类型</div><div>    * reactive：将数据变为响应式数据，只能用于引用类型数据 【注意】：在 js 中使用 ref 响应式数据，需要加.value</div><div>2、ref 和 reactive 响应式原理不同</div><div>    * ref:对于基本数据类型的数据使用 Object.defineProperty()进行响应式，对于引用数据类型的数据使用 proxy 进行响应式</div><div>    * reactive:只能用于引用数据类型，使用 proxy 进行响应式</div><div>3、使用reactive时，对响应式对象重新赋值是会失去响应式的，ref则没有这种问题。</div></div><div><br/></div><div><span style="font-size: 16pt;"><span style="font-size: 16pt; font-weight: bold;">less和sass的区别</span></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>less和sass都是CSS的预处理器，其基本思想就是用编程的思路编写CSS代码。增加了变量，嵌套，函数，混入，继承等概念。有助于模块化开发</div><div><br/></div><div>不同:</div><div>1、Less环境较Sass简单</div><div>2、Less使用较Sass简单</div><div>3、从功能出发，Sass较Less强大</div><div>4、Less与Sass处理机制不一样</div><div>5、变量符不一样，less是@，sass是$</div><div><br/></div><div>https://juejin.cn/post/7226287155668156474?searchId=2023081711162761BC1F1641E86DDF16F9#heading-17</div></div><div><br/></div><div><span style="font-size: 16pt;"><b>从输入url到页面渲染全过程</b></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7252869090549268538?searchId=20230823134355BCA29243F9D9B41855E8#heading-0</div></div><div><br/></div><div><span style="font-size: 21.3333px;"><b>前端安全</b></span></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/7009959778147385374?searchId=2023082314411616C1FB034BA14320F43B#heading-1</div></div><div><br/></div><div><b style="font-size: 21.3333px; color: unset; font-family: unset;">文件上传</b><br/></div><div><br/></div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>https://juejin.cn/post/6844903860327186445?searchId=20230823175554679B31874DF8EB3CCF49#heading-8</div></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div></span>
</div></body></html> 